package compilarclassejava;

import java.lang.reflect.Method;
import java.util.LinkedList;

import entidadesparaguardardadosteste.CasoDeTeste;
import gui.AssociaClassesEMetodosANomes;
import gui.DeclaracaoDeMetodo;
import gui.FachadaManipulacaoClassesDeUmProjeto;

/*apos terminarmos de fazer as devidas modificacoes no arquivo .java com a classe a ser testada
 * que o cliente informou, precisamos criar um caso de teste para esse novo .class (nos compilamos
 * o .java para criar um novo .class) de forma que o metodo MAIN seja testado.
 * Esse caso de teste nao sera totalmente completo. Ele tera todo o necessario para ser executado,
 * exceto por valores de entrada e saidas esperadas
 * */
public class PreparaCasoDeTesteComMain 
{	
	public CasoDeTeste prepararCasoDeTesteParaMainSemEntradasESaidasEsperadas
										(String enderecoParaArquivoJavaQueCriamos)
	{
		String caminhoAteNovaPastaComJavaEClassQueCriamos = "backupsTestable";
		
		String nomeClasseAssociadaAoCasoDeTeste =
				obterNomeDaClasseASerTestada(enderecoParaArquivoJavaQueCriamos);
		
		FachadaManipulacaoClassesDeUmProjeto fachadaClassesDoProjeto =
											FachadaManipulacaoClassesDeUmProjeto.getInstance();
		AssociaClassesEMetodosANomes conheceAsClassesDoProjeto =
									 fachadaClassesDoProjeto.getAssociaClassesEMetodosANomes();
		
		
		@SuppressWarnings("rawtypes")
		Class classeQueVamosTestar = conheceAsClassesDoProjeto.pegarClasseDeNome(nomeClasseAssociadaAoCasoDeTeste);
		
		/*vamos obter todas as informacoes necessarias para criar um caso de teste sem parametros
		 * de entrada ou saida. As unicas que precisamos obter sao nome da classe a ser testada
		 * e declaracao de metodo Main (que queremos testar)*/
		Method metodoMainASerTestado = pegarMetodoMainDeUmaClasse(classeQueVamosTestar);
		
		DeclaracaoDeMetodo declaracaoDeMetodoMain =
				new DeclaracaoDeMetodo(metodoMainASerTestado, enderecoParaArquivoJavaQueCriamos);
		declaracaoDeMetodoMain.setCabecalhoDoMetodo("void main(String args [])");
		
		/*agora vamos finalmente criar o caso de testes incompleto*/
		
		CasoDeTeste casoDeTesteParaMainSemEntradasESaidasEsperadas = 
				this.criarCasoDeTesteComBaseEmInformacoesRecolhidas
					(caminhoAteNovaPastaComJavaEClassQueCriamos, nomeClasseAssociadaAoCasoDeTeste,
																			declaracaoDeMetodoMain);
		return casoDeTesteParaMainSemEntradasESaidasEsperadas;
	}
	
	private Method pegarMetodoMainDeUmaClasse(@SuppressWarnings("rawtypes") Class classe)
	{
		Method[] metodosDaClasse = classe.getMethods();
		for(int i = 0; i < metodosDaClasse.length; i++)
		{
			Method umMetodo = metodosDaClasse[i];
			if(umMetodo.getName().compareToIgnoreCase("main") == 0)
			{
				//achamos o metodo main da classe
				return umMetodo;
			}
		}
		
		System.out.println("////AVISO: METODO MAIN DA CLASSE NAO ENCONTRADO!!!!");
		return null;
	}
	
	private String obterNomeDaClasseASerTestada(String enderecoParaArquivoJavaModificado)
	{
		String[] stringSplitadaPorBarras = enderecoParaArquivoJavaModificado.split("/");
		String parteDoEnderecoComNomeDaClasseEExtensaoJava =
				stringSplitadaPorBarras[stringSplitadaPorBarras.length - 1];
		String nomeClasseJavaSemExtensao =
				parteDoEnderecoComNomeDaClasseEExtensaoJava.replaceAll(".java", "");
		nomeClasseJavaSemExtensao = nomeClasseJavaSemExtensao.replace(".c", "");
		String nomeClasseASerTestada = nomeClasseJavaSemExtensao.replace(" ", "");
		
		return nomeClasseASerTestada;
	}
	
	private CasoDeTeste criarCasoDeTesteComBaseEmInformacoesRecolhidas
				(String enderecoDoProjetoDaClasseATestar, String nomeClasseAssociadaAoCasoDeTeste, 
																			DeclaracaoDeMetodo metodo)
	{
		CasoDeTeste casoDeTeste = new CasoDeTeste();
		casoDeTeste.setIdCasoDeTeste(0);
		casoDeTeste.setEnderecoDoProjetoDaClasseATestar(enderecoDoProjetoDaClasseATestar);
		casoDeTeste.setNomeClasseAssociadaAoCasoDeTeste(nomeClasseAssociadaAoCasoDeTeste);
		casoDeTeste.setMetodo(metodo);
		//main tem parametro String args[] que quase nunca eh usado...
		String args [] = new String [0];
		LinkedList<Object> parametrosDoMetodoTestar = new LinkedList<Object>();
		parametrosDoMetodoTestar.add(args);
		casoDeTeste.setValoresDosParametrosDoMetodo(parametrosDoMetodoTestar);
		casoDeTeste.setCasoDeTesteEstahCompleto(true);
		
		return casoDeTeste;
	}
}
